﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HalconDotNet;

using System.Runtime.InteropServices;

using System.Windows.Forms;

using MvCamCtrl.NET;

using System.IO;


namespace CamHKVision
{

    public class CamHKVisionActioner:ImageDefine.CameraActionerBase
    {
        object objLock;
        HImage image;

        UInt32 nPayloadSize;
        MyCamera device = new MyCamera();

        public MyCamera.cbOutputExdelegate ImageCallback;

        public delegate void GetNewFlyImage(HImage inputImage);
        public event GetNewFlyImage getNewFlyImage;
        CamHKVision camHKVision;
        public CamHKVisionActioner()
        {
            objLock = new object();
            setting = new ImageDefine.CameraToolBase();
        }
        public CamHKVisionActioner(CamHKVision toolBase)
        {
            objLock = new object();
            setting = toolBase;
            camHKVision = toolBase;


        }
        public override HImage GrabImage()
        {
            HImage imageTemp = Grab();
            CamHKVisionSetting camSetting = ((CamHKVision)setting).camGeneralSetting;
            if (camSetting.MirrorRow)
            {
                imageTemp = imageTemp.MirrorImage("row");
            }
            if (camSetting.MirrorCol)
            {
                imageTemp = imageTemp.MirrorImage("column");
            }
            if (camSetting.NeedRotate)
            {
                imageTemp = imageTemp.RotateImage(camSetting.dRotateAngle, "constant");
            }
            if (camSetting.CropImage)
            {
                int iTempImageWidth,iTempImageHeight;
                imageTemp.GetImageSize(out iTempImageWidth, out iTempImageHeight);
                imageTemp=imageTemp.CropPart(iTempImageHeight / 2 - camSetting.ImageHeight / 2,iTempImageWidth / 2 - camSetting.ImageWidth / 2, camSetting.ImageWidth, camSetting.ImageHeight);
                
            }
            if(camSetting.TragMode==false && imageTemp==null)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (image == null)
                    {
                        InitCam("Again");
                    }
                    else
                    {
                        break;
                    }
                    imageTemp = Grab();
                    if (camSetting.MirrorRow)
                    {
                        imageTemp = imageTemp.MirrorImage("row");
                    }
                    if (camSetting.MirrorCol)
                    {
                        imageTemp = imageTemp.MirrorImage("column");
                    }
                    if (camSetting.NeedRotate)
                    {
                        imageTemp = imageTemp.RotateImage(camSetting.dRotateAngle, "constant");
                    }
                    if (camSetting.CropImage)
                    {
                        int iTempImageWidth, iTempImageHeight;
                        imageTemp.GetImageSize(out iTempImageWidth, out iTempImageHeight);
                        imageTemp = imageTemp.CropPart(iTempImageHeight / 2 - camSetting.ImageHeight / 2, iTempImageWidth / 2 - camSetting.ImageWidth / 2, camSetting.ImageWidth, camSetting.ImageHeight);

                    }
                }
            }
            return imageTemp;
        }
        bool bAlreadyGetImage = false;
        int iFileImageIndex = 0;
        List<string> listImageFileNames;
        private HImage Grab()
        {

            // 申请内存按照目前相机最大分辨率设计，实际根据一帧大小可更改
            if (camHKVision.camGeneralSetting.UseSampleImage)
            {
                if (listImageFileNames == null)
                {
                    listImageFileNames = new List<string>();
                    string[] fileNames = Directory.GetFiles(Application.StartupPath + @"/Cam/");
                    foreach (string fileName in fileNames)
                    {
                        listImageFileNames.Add(fileName);
                    }
                    iFileImageIndex = 0;
                }
                int iTempIndex = iFileImageIndex;
                iFileImageIndex = iFileImageIndex + 1;
                if (iFileImageIndex == listImageFileNames.Count)
                {
                    iFileImageIndex = 0;
                }
                image = new HImage(listImageFileNames[iTempIndex]);
                return image;
            }
            device.MV_CC_TriggerSoftwareExecute_NET();

            bAlreadyGetImage = false;
            GeneralLib.HiPerfTimer hiTimer = new GeneralLib.HiPerfTimer();
            hiTimer.Start();
            // 获取一帧图像
            while (true)
            {
                if (bAlreadyGetImage)
                {
                    return image;
                }
                if (hiTimer.TimeUp(5))
                    break;

            }
            return null;
        }
        
        public override void Close()
        {
            int nRet = MyCamera.MV_OK;
            if (bInitOk)
            {
                
                // ch:关闭设备 | en:Close device
                nRet = device.MV_CC_CloseDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    return;
                }

                // ch:销毁设备 | en:Destroy device
                nRet = device.MV_CC_DestroyDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    return;
                }
                bInitOk = false;
            }
        }
        public override void InitCam(string strFullName)
        {
            int nRet;
            MyCamera.MV_CC_DEVICE_INFO_LIST m_pDeviceList;
            m_pDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
            CamHKVisionSetting camSetting = ((CamHKVision )setting).camGeneralSetting;

            nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_pDeviceList);
            MyCamera.MV_CC_DEVICE_INFO deviceInfo=new MyCamera.MV_CC_DEVICE_INFO();
            bool bMatchIp = false;
            if (m_pDeviceList.nDeviceNum > 0)
            {
                for (int i = 0; i < m_pDeviceList.nDeviceNum; i++)
                {
                    deviceInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_pDeviceList.pDeviceInfo[i],
                                                                  typeof(MyCamera.MV_CC_DEVICE_INFO));
                    string strMes = deviceInfo.SpecialInfo.stGigEInfo[11].ToString() + "." + deviceInfo.SpecialInfo.stGigEInfo[10].ToString() + "." + deviceInfo.SpecialInfo.stGigEInfo[9].ToString() + "." + deviceInfo.SpecialInfo.stGigEInfo[8].ToString();
                    if (strMes == camSetting.DeviceIpAddress)
                    {
                        bMatchIp = true;
                        break;
                    }
                }
            }
            if (bMatchIp == false)
            {
                //MessageBox.Show("CamIP Not Found");
                bInitOk = false;
                return;
            }
            nRet = device.MV_CC_CreateDevice_NET(ref deviceInfo);
            if (MyCamera.MV_OK != nRet)
            {
                //MessageBox.Show("Create device failed");
                bInitOk = false;
                return;
            }
            
            // ch:打开设备 | en:Open device
            nRet = device.MV_CC_OpenDevice_NET();
            if (MyCamera.MV_OK != nRet)
            {
                MessageBox.Show("Open device failed");
                bInitOk = false;
                return;  
            }


            nRet = device.MV_CC_SetEnumValue_NET("TriggerMode", 1);
            if (MyCamera.MV_OK != nRet)
            {
                MessageBox.Show("Set TriggerMode failed!");
                bInitOk = false;
                return;
            }
            if (camSetting.TragMode)
            {
                device.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
                
            }
            else
            {
                nRet = device.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
            }
            if (MyCamera.MV_OK != nRet)
            {
                MessageBox.Show("Set TriggerSource failed!");
                bInitOk = false;
                return;
            }
            ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
            nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
            //ch: 开启抓图 || en: start grab image
            nRet = device.MV_CC_StartGrabbing_NET();
            if (MyCamera.MV_OK != nRet)
            {
                MessageBox.Show("Start grabbing failed!");
                bInitOk = false;
                return;

            }

            // ch:获取包大小 || en: Get Payload Size
            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            nRet = device.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (MyCamera.MV_OK != nRet)
            {
                MessageBox.Show("Get PayloadSize failed!");
                bInitOk = false;
                return;

            }
            nPayloadSize = stParam.nCurValue;
            device.MV_CC_SetHeartBeatTimeout_NET(1000);
            SetShutter(camHKVision.camGeneralSetting.ExporsureMs);
            SetGain(camHKVision.camGeneralSetting.Gain);
            bInitOk = true;
        }
        public override void SetGainAndShutter(int gain, double shutter)
        {

            int iInputExporsureMs = (int)(shutter);
            int iCurrentExporsureMs = (int)(setting.dExporsureMs);
            int iInputGain = (int)(gain);
            int iCurrentGain = (int)(setting.iGain);
            //if (iCurrentExporsureMs != iInputExporsureMs || iInputGain != iCurrentGain)
            {
                try
                {
                    device.MV_CC_SetGain_NET(iInputGain);
                    device.MV_CC_SetExposureTime_NET(iInputExporsureMs);
                    setting.dExporsureMs = shutter;
                    setting.iGain = gain;
                }
                catch
                {

                }
                //camera.Parameters[PLCamera.AcquisitionMode].GetValue

            }

        }
        public override void ShowFrm(string name)
        {
            FormSetting frmSetting = new FormSetting();
            frmSetting.camGeneral = (CamHKVision )this.setting;
            frmSetting.strName = setting.strName;
            frmSetting.Show();
        }

        override public void SetGain(int gain)
        {
            try
            {
                device.MV_CC_SetGain_NET(gain);
                setting.iGain = gain;
            }
            catch
            {

            }
        }
        override public void SetShutter(double shutter)
        {
            int iInputExporsureMs = (int)(shutter);
            try
            {
                device.MV_CC_SetExposureTime_NET(iInputExporsureMs);
                setting.dExporsureMs = shutter;
            }
            catch
            {

            }
        }
        override public int GetGain()
        {
            try
            {
                MyCamera.MVCC_FLOATVALUE iValue=new MyCamera.MVCC_FLOATVALUE();

               device.MV_CC_GetGain_NET(ref iValue);
                return (int)(iValue.fCurValue);
            }
            catch
            {
                return 0;
            }
        }
        override public double GetShutter()
        {
            try
            {
                MyCamera.MVCC_FLOATVALUE iValue = new MyCamera.MVCC_FLOATVALUE();
                double lValue = device.MV_CC_GetExposureTime_NET(ref iValue);
                double iCurrentExporsureMs = (double)(iValue.fCurValue);
                return iCurrentExporsureMs;
            }
            catch
            {
                return 0.0;
            }
        }
        override public void SetTragMode(bool bTragOn)
        {
            try
            {
                if (bTragOn)
                {
                     device.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
                    device.MV_CC_SetEnumValue_NET("TriggerMode", 1);
                }
                else
                {
                     device.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
                    device.MV_CC_SetEnumValue_NET("TriggerMode", 1);
                }
                CamHKVisionSetting camSetting = ((CamHKVision)setting).camGeneralSetting;
                camSetting.TragMode = bTragOn;
            }
            catch
            {

            }

        }
        public bool GetInput1()
        {
            //int nRet;
            //MyCamera.MVCC_ENUMVALUE stModeValue = new MyCamera.MVCC_ENUMVALUE();
            //nRet = device.MV_CC_GetEnumValue_NET("LineMode", ref stModeValue);
            return true;
        }
        override public bool GetTragMode()
        {
            CamHKVisionSetting camSetting = ((CamHKVision)setting).camGeneralSetting;
            return camSetting.TragMode;
           
        }
        bool bStartFlyCatch = false;
        public void StartFlyGrab()
        {
            device.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
            device.MV_CC_SetEnumValue_NET("TriggerMode", 1);
            bStartFlyCatch = true;
        }
        public void StopFlyGrab()
        {
            device.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
            device.MV_CC_SetEnumValue_NET("TriggerMode", 1);
            bStartFlyCatch = false;
        }
        void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
        {
            if (bStartFlyCatch==false)
            {
                if (image != null)
                {
                    image.Dispose();
                }
                image = new HImage();
                if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
                {
                    image.GenImage1("byte", pFrameInfo.nWidth, pFrameInfo.nHeight, pData);
                }
                else
                {
                    image.GenImageInterleaved(pData, "rgb", pFrameInfo.nWidth, pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
                }
            }
            else
            {
                
                    HImage ImageNew = new HImage();
                    if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
                    {
                        ImageNew.GenImage1("byte", pFrameInfo.nWidth, pFrameInfo.nHeight, pData);
                    }
                    else
                    {
                        ImageNew.GenImageInterleaved(pData, "rgb", pFrameInfo.nWidth, pFrameInfo.nHeight, -1, "byte", 0, 0, 0, 0, -1, 0);
                    }
                    CamHKVisionSetting camSetting = ((CamHKVision)setting).camGeneralSetting;
                    if (camSetting.MirrorRow)
                    {
                        ImageNew = ImageNew.MirrorImage("row");
                    }
                    if (camSetting.MirrorCol)
                    {
                    ImageNew = ImageNew.MirrorImage("column");
                    }
                    if (camSetting.NeedRotate)
                    {
                    ImageNew = ImageNew.RotateImage(camSetting.dRotateAngle, "constant");
                    }
                    if (camSetting.CropImage)
                    {
                        int iTempImageWidth, iTempImageHeight;
                        ImageNew.GetImageSize(out iTempImageWidth, out iTempImageHeight);
                        ImageNew = ImageNew.CropPart(iTempImageHeight / 2 - camSetting.ImageHeight / 2, iTempImageWidth / 2 - camSetting.ImageWidth / 2, camSetting.ImageWidth, camSetting.ImageHeight);

                    }
                Task.Factory.StartNew(() =>
                    {
                        if (getNewFlyImage != null)
                        {
                            getNewFlyImage(ImageNew);
                        }
                    });
               
            }
            bAlreadyGetImage = true;
            return;
        }
    }
   
}
